# -*- coding: utf-8 -*-
# @author: Florian Dorn <florian.dorn@gmail.com>
# @package: agenda
# @license: GNU GPLv2
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.



#GtkTreeView::odd_row_color
#
import gtk

import glib
import gobject
import datetime

from math import pi as M_PI
M_PI_1_5 = M_PI*1.5
M_PI_0_5 = M_PI*0.5




from EventWidget import EventWidget
from agenda import FilterType
from agenda import ANOTHER_DAY_FMT
from agenda import get_timeout_add_time


class DateWidget (gtk.EventBox):
	__gtype_name__ = 'DateWidget'
	#bg colors are cairo colors [0-1]	
	color_today_bg = (.9,.9,0)
	#these are the colors that are used by nautilus
	color_odd_bg = (.86328125,.86328125,.86328125) ##DDDDDD
	color_even_bg = (.9296875,.9296875,.9296875)  ##EEEEEE
	
	#fg_colors are gtk_colors
	color_today_fg = gtk.gdk.Color(65535,65535,65535)
	color_odd_fg = gtk.gdk.Color(0,0,0)
	color_even_fg = gtk.gdk.Color(0,0,0)
	
	def __repr__(self):
		return "%s, %s" % (self.__module__,self.date)
	def __init__(self, date):
		self.date = None
		self.row_number = -1
		gtk.EventBox.__init__(self)
		self.set_border_width(8)
		
		widget = gtk.VBox()
		#widget = self
		#widget.set_border_width(5)
		
		"""header holds the day, and the date"""
		header = gtk.HBox()
		self.day_label = gtk.Label('day')
		self.day_label.set_alignment(0,0.5)
		
		
		self.dateW = gtk.Label('date')
		self.dateW.set_alignment(1,0.5)
		header.pack_start(self.day_label,True,True,2)
		header.pack_start(self.dateW)
		
		widget.pack_start(header)

		"""Container holds the events in this widget"""
		container = gtk.VBox()
		self.container = container
		self.container.set_no_show_all(False)
		#abstand vom rand
		al = gtk.Alignment(.5,.5,1,1)
		al.set_padding(0,0,12,0)
		al.add(container)
		#hbox13.pack_start(container,True,True)
		widget.pack_start(al)
		self.day = date.strftime("%A")
		self.day_label.set_markup('<span size="larger">%s</span>' % self.day)
		self.dateW.set_markup('<span size="smaller">%s</span>' % (date.strftime(ANOTHER_DAY_FMT)))

		self.add(widget)
		self.set_visible_window(False)

		self.date = date
		self._timeout_redraw = -1
		
		self.update_ui()
		

		
		self.connect ("expose-event",	self.after_expose_cb) # (re)draw
		self.connect ("notify::style",	self.set_styles) # gtk theme changes

		self.container.connect_after ("remove",			self.on_child_remove)

		widget.show_all()
		#widget.show()
		#todo: move this code to the listview
	def set_styles (self, obj=None, prop=None):
		"""
		update the style
		"""
		
		if(self.row_number % 2 == 0):
			fg = DateWidget.color_odd_fg
		else:
			fg = DateWidget.color_even_fg
		
		self.day_label.modify_fg(self.day_label.state, 	fg)
		self.dateW.modify_fg(self.dateW.state, 			fg)

	def after_expose_cb(self, a, event):
		#print "exposing"
		#gtk.EventBox.do_expose_event(self, event)
		x,y,width, height = self.get_allocation()
		cr = self.window.cairo_create()
		
		# Restrict Cairo to the exposed area; avoid extra work
		cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
		if(self.row_number % 2 == 0):
			r,g,b = DateWidget.color_odd_bg
		else:
			r,g,b = DateWidget.color_even_bg
		cr.set_source_rgb(r, g, b)
		self.draw_rounded_rectangle(cr,x,y,width,height,8,2)
		cr.fill()
		
		#draw selection frame on the today widget
		if(self.date == datetime.datetime.today().date()):
			r,g,b = DateWidget.color_today_bg
			cr.set_source_rgb(r, g, b)
			cr.set_line_width(max(cr.device_to_user_distance(2, 2)))
			self.draw_rounded_rectangle(cr,x,y,width,height,6,3)
		cr.stroke()
		
	def update_ui(self):
		self.set_styles()
		"""
		update the ui and install a timeout to redraw when the ui should be updated next
		this is if the day ends and the day starts
		"""
		if(self._timeout_redraw != -1):
			gobject.source_remove(self._timeout_redraw)
		
		nextdraw_micro = get_timeout_add_time(datetime.datetime.combine(self.date,datetime.time()))
		if(nextdraw_micro > 0):
			self._timeout_redraw = gobject.timeout_add(nextdraw_micro, self.update_ui)
		nextdraw_micro = get_timeout_add_time( datetime.datetime.combine(self.date,datetime.time()) + datetime.timedelta(days=1) )
		if(nextdraw_micro > 0):
			self._timeout_redraw = gobject.timeout_add(nextdraw_micro, self.update_ui)
	
		gobject.idle_add(self.queue_draw)
		return False
	def get_event(self,cal_event):
		"""
		get the event and store it
		"""
		ev = EventWidget(cal_event)
		ev.set_no_show_all(True)
		return ev
	def add_event(self,cal_event):
		"""
		add a Event to this date widget
		"""
		if(self.date != cal_event.start_time.date()):
			print "the event is not suitable for this date"
			#raise Exception
			#return
		#get the widget for this cal_event
		event_widget = self.get_event(cal_event)
		event_widget.connect ("notify::visible", self.child_visibility_changed) # child visibility changed
		#add it to the container
		self.container.pack_start(event_widget,False,False,2)
		#reorder the container
		new_pos = -1
		
		for i,child in enumerate(self.container.get_children()):
			if(child.event > cal_event):
				#print "moving %s to position %s" % (cal_event,i)
				self.container.reorder_child(event_widget,i)
				break
		pass
	def remove_event(self,cal_event):
		ew = None
		for ew in self.container.get_children():
			if	ew.event == cal_event:
				break
		if ew:
			#print "... OK"
			self.container.remove(ew)
		else:
			"... is not in date widget list"


	def filter(self,filter):
		found_any = False
		children = self.container.get_children()
		for c in children:
			if not c.event.is_visible():
				c.hide()
				continue
			found = c.filter(filter)
			if(not found):
				c.hide()
			else:
				found_any = True
				c.show()
		return found_any
	def set_row_number(self,k):
		if(k != self.row_number):
			self.row_number = k

	def draw_rounded_rectangle (self, cr, x, y, w, h, radius,offset):
		'''Draw a rounded rectangle path'''
		#cr = gdk_cairo_create (GDK_DRAWABLE (window));
		x = x+offset
		y = y+offset
		h = h-2*offset
		w = w-2*offset
		cr.new_path ()
		cr.arc ( x + radius, y + radius, radius, M_PI, M_PI_1_5)
		cr.arc ( x + w - radius, y + radius, radius, M_PI_1_5, 0)
		cr.arc ( x + w - radius, y + h - radius, radius, 0, M_PI_0_5)
		cr.arc ( x + radius, y + h - radius, radius, M_PI_0_5, M_PI)
		cr.close_path ()
		
	def is_visible(self):
		return self.get_property("visible")

	def child_visibility_changed(self,parent=None, pspec=None):
		"""
		if all childs are invisible, then hide it,
		else show
		"""
		
		if not self.has_visible_children():
			self.hide()
		else:
			self.show()
	def show(self):
		"""
		"""
		if not self.has_visible_children():
			return
		else:
			gtk.EventBox.show(self)
	def has_visible_children(self):
		"""
		return true if the Widget has visible children
		"""
		if self.date == datetime.date.today():
			return True
		children = self.container.get_children()
		for widget in children:
			if widget.props.visible:
				return True
		return False
	def on_child_remove(self,container=None,child=None):
		self.child_visibility_changed()
